//
// Created by 11510 on 2024/7/8.
//

#ifndef REACTOR_SOCKETIO_H
#define REACTOR_SOCKETIO_H
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

class SocketIO {
private:
    int _fd;

public:
    explicit SocketIO(int fd):_fd(fd){}
    ~SocketIO(){
        close(_fd);
    }

    int readn(char* buf, int len){
        int left = len;
        char *pstr = buf;
        int ret;

        while(left > 0){
            /* 为何不用recv？ */
            ret = read(_fd, pstr, left);

            if(-1 == ret && errno == EINTR){
                /* 被中断了 */
                continue;

            }else if(-1 == ret){
                perror("read error -1");
                return -1;

            }else if(0 == ret){
                /* 对端关闭 */
                break;

            }else{
                pstr += ret;
                left -= ret;
            }
        }

        return len - left;
    }

    int writen(const char* buf, int len){
        int left = len;
        const char *pstr = buf;
        int ret;

        while (left > 0) {
            ret = write(_fd, pstr, left);

            if (-1 == ret && errno == EINTR) {
                continue;

            } else if (-1 == ret) {
                perror("writen error -1");
                return -1;

            } else if (0 == ret) {
                break;

            } else {
                pstr += ret;
                left -= ret;
            }
        }
        return len - left;
    }

    int readLine(char* buf, int len){
        int left = len - 1; /* left 是还能读取的最大长度 */
        char *pstr = buf;
        int ret, total = 0;

        while (left > 0) {
            //MSG_PEEK不会将缓冲区中的数据进行清空,只会进行拷贝操作
            ret = recv(_fd, pstr, left, MSG_PEEK);
            if (-1 == ret && errno == EINTR) {
                continue;

            } else if (-1 == ret) {
                perror("readLine error -1");
                return -1;

            } else if (0 == ret) {
                /* 对端断开 */
                break;

            } else {
                for (int idx = 0; idx < ret; ++idx) {
                    if (pstr[idx] == '\n') {
                        int sz = idx + 1;
                        readn(pstr, sz);
                        pstr += sz;
                        *pstr = '\0';//C风格字符串以'\0'结尾

                        /**
                         * 这里返回一定是一行读到
                         */
                        return total + sz;
                    }
                }

                readn(pstr, ret);//从内核态拷贝到用户态
                total += ret;
                pstr += ret;
                left -= ret;
            }
        }
        /**
         * 从这里返回是刚好读完或没读完
         */
        *pstr = '\0';
        return total - left;
    }

};


#endif //REACTOR_SOCKETIO_H
